package com.proxy.scanandcheck.scaner.thread;

import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.apache.log4j.Logger;

import com.proxy.scanandcheck.common.util.Constants;
import com.proxy.scanandcheck.common.util.IPUtil;
import com.proxy.scanandcheck.common.valueobject.ProxyRequest;
import com.proxy.scanandcheck.scaner.valueobject.IpAddress;
import com.proxy.scanandcheck.scaner.valueobject.StartEndIp;

public class ScannerByPossibleIpThreadPool extends AbstractScannerThreadPool{
	
	private static final Logger LOGGER = Logger.getLogger(ScannerByPossibleIpThreadPool.class);
	
	public boolean execute(ProxyRequest proxyRequest) throws InterruptedException, ExecutionException
	{
		super.setStarted(Boolean.TRUE);
		
		super.setThreadPoolExecutor( 
				new ThreadPoolExecutor(proxyRequest.getThreadCount(), 
				Integer.MAX_VALUE, Constants.KEEP_ALIVE_TIME,
				TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1000),
				new ThreadPoolExecutor.CallerRunsPolicy())
		);
		
		long startIpLong = 0,endIpLong = 0;
		
		List<StartEndIp> result = new ArrayList<StartEndIp>();
		Scanner scanner = new Scanner(AbstractScannerThreadPool.class.getResourceAsStream(Constants.POSSIBLE_PROXIES_TXT_PATH));
		List<ScannerThreadPoolTask> scannerThreadPoolTaskList = new ArrayList<ScannerThreadPoolTask>();
		int i = 0;
		List<IpAddress> ipAddressList = new ArrayList<IpAddress>();
		while(scanner.hasNext())
		{
			String line = scanner.next();
			String lineArr [] = line.split(",");
			startIpLong = IPUtil.ip2Long(lineArr[0]);
			endIpLong = IPUtil.ip2Long(lineArr[1]);
			for(long ipLong = startIpLong; ipLong < endIpLong; ipLong ++)
			{
				String ip = IPUtil.long2IP(ipLong);
				if(!IPUtil.isPrivateIp(ip))
				{
					for(int port = 0; port < Constants.ANOTHER_PORTS.length; port ++)
					{
						IpAddress ipAddress = new IpAddress(ip, Constants.ANOTHER_PORTS[port], proxyRequest.getIpClass());
						ipAddressList.add(ipAddress);
						ScannerThreadPoolTask scannerThreadPoolTask = new ScannerThreadPoolTask(ipAddress);
						scannerThreadPoolTaskList.add(scannerThreadPoolTask);
//						LOGGER.info(ipAddress);
						
						i ++;
						if(i % 1000 == 0)
						{
							LOGGER.info("------ Scan from " + 
									ipAddressList.get(0) + 
									" - " + 
									ipAddressList.get(ipAddressList.size() - 1) + 
									", size: " + 
									ipAddressList.size());
							
							getThreadPoolExecutor().invokeAll(scannerThreadPoolTaskList);
							
							getProxyCheckingController().startCheck(
									getProxyList(ipAddressList), 
									proxyRequest.getKeyWordsList());
							
							ipAddressList.clear();
							scannerThreadPoolTaskList.clear();
							
							Thread.sleep(2000);
						}
					}
				}
			}
		}
		
		return Boolean.TRUE;
	}

	public List<IpAddress> getIpAddressList(ProxyRequest proxyRequest) {
		List<StartEndIp> startEndIpList = null;
		try {
			startEndIpList = super.getScannerDao().getPossibleIpAddressList();
		} catch (FileNotFoundException e) {
			LOGGER.error(e);
			throw new RuntimeException(e);
		}
		List<IpAddress> result = new ArrayList<IpAddress>();
		for(StartEndIp startEndIp : startEndIpList)
		{
			long startIpLong = IPUtil.ip2Long(startEndIp.getStartIp());
			long endIpLong = IPUtil.ip2Long(startEndIp.getEndIp());
			
			for(long ipLong = startIpLong; ipLong < endIpLong; ipLong ++)
			{
				String ip = IPUtil.long2IP(ipLong);
				if(!IPUtil.isPrivateIp(ip))
				{
					for(int port = 0; port < Constants.ANOTHER_PORTS.length; port ++)
					{
						IpAddress ipAddress = new IpAddress(ip, Constants.ANOTHER_PORTS[port], proxyRequest.getIpClass());
						result.add(ipAddress);
//						LOGGER.info(ipAddress);
					}
				}
			}
		}
		return result;
	}

}
